package com.mumulx.check.web.config.security;

import com.mumulx.check.service.service.UserInfoService;
import com.mumulx.check.service.service.impl.UserInfoServiceImpl;
import com.mumulx.check.web.config.security.auth.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
import org.springframework.security.web.firewall.DefaultHttpFirewall;
import org.springframework.security.web.firewall.HttpFirewall;

import javax.annotation.Resource;
import javax.sql.DataSource;

/*
 *  Created by IntelliJ IDEA.
 *  User: 木木
 *  Date: 2020/10/25
 *  Time: 20:51
 */
@Slf4j
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /*登录成功*/
    @Resource
    MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    /*推出成功*/
    @Resource
    MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private DataSource dataSource;//对应的是application-dev.yml中的datasource
    /*我的加密算法*/
    //@Autowired
    //private PasswordEncoder passwordEncoder;

    @Autowired
    UserInfoServiceImpl myUserDetailsService;

    /*超时session响应策略**/
    @Resource
    MyExpiredSessionStrategy myExpiredSessionStrategy;

    @Override
    public void configure(WebSecurity web) throws Exception {

        web.ignoring().antMatchers("/ajax/**","/check/**","/css/**","/fonts/**","/images/**","/js/**","/plugins/**","/favicon.ico");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception { //配置策略
        http.csrf().disable()//关掉csrf，否则会将我们的请求当作是一个不合法的
                .authorizeRequests()
                .antMatchers("/remoteserver/**",
                        "/UserInfo/frontLogin",
                        "/login",
                        "/info/**",
                        "/fileupload",
                        "/testrecord",
                        "/testresult",
                        "/help/getVerifyCode",
                        "/UserInfo/getLoginUserInfo",
                        "/UserInfo/checkAuthCode"
                )

                .permitAll().anyRequest().authenticated()
            .and().formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/UserInfo/frontLogin")//登录验证请求  post方式的表单action
                //.successForwardUrl("/help/index")//登陆成功  这里不配置登录成功时跳转的页面  前端采用ajax方式提交登录 我们返回一个json结果，由前端决定页面的跳转
                //.failureForwardUrl("/intoFail")//登录失败
                .successHandler(myAuthenticationSuccessHandler)
                .failureHandler(myAuthenticationFailureHandler)
                .permitAll()
            .and().logout()
                .logoutUrl("/logout")//指定登出路径
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .deleteCookies("remember-me-cookie")
                .logoutSuccessUrl("/login")//登出成功后跳转的url
                .permitAll()
                //.logoutSuccessHandler(myLogoutSuccessHandler)
            .and().rememberMe()
                .userDetailsService(myUserDetailsService)
                .rememberMeParameter("rememberMe")//传参的名称即，ajax请求中"remember-me":rememberMe
                .rememberMeCookieName("remember-me-cookie")//cookie的name
                .tokenValiditySeconds(2*24*60*60)//过期时间：两天
                .tokenRepository(persistentTokenRepository())
            .and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .invalidSessionUrl("/help/error")//用户在  超时后返回登录页面   发送的请求  可以定义controller处理它
                .sessionFixation().migrateSession()//session保护  每次复制一个session
                .maximumSessions(1)//最大登录的人数  不起作用的原因是 user detail没有重写equals hashcode  https://blog.csdn.net/xusanhong/article/details/53260373
                .maxSessionsPreventsLogin(false)//true:登录之后不能再登录，false：允许再次登录，但是前一次登录会下线
                .expiredSessionStrategy(myExpiredSessionStrategy)//超时session响应策略  多个用户同时登录
        ;
    }




    /*remember-me功能将用户信息记录到数据库中*/
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){

        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        return tokenRepository;
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new MyPasswordEncoder();
    }
    /**
     * https://blog.csdn.net/yuanlaijike/article/details/95104553
     *
     * 在MyAuthenticationFailureHandler 中可以区分异常的类型 返回不同的提示信息
     * */
 /*   @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setHideUserNotFoundExceptions(false);
        provider.setUserDetailsService(myUserDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        return provider;
    }*/

}
